package com.example.xmlfind.ui;

import com.example.xmlfind.entity.FindResult;
import com.example.xmlfind.worker.FindWorker;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.ScrollingModel;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.HashSet;

public class FindUI {
    private Project project;
    private JPanel mainPanel;
    private JTextField valueField;
    private JTextField keyField;
    private JTextField nameField;
    private JButton choiceButton;
    private JList<FindResult> findList;
    private JLabel dirLabel;
    private JLabel nameLabel;
    private JLabel keyLabel;
    private JLabel valueLabel;
    private JList<VirtualFile> dirList;
    private JButton findButton;
    private JButton cancelButton;
    private JProgressBar findProgress;
    private DefaultListModel<VirtualFile> dirModel = new DefaultListModel<>();
    private DefaultListModel<FindResult> findModel = new DefaultListModel<>();

    private FindWorker worker;

    public FindUI(Project project) {
        this.project = project;

        dirList.setModel(dirModel);
        findList.setModel(findModel);

        // 设置列表渲染器
        dirList.setCellRenderer(new DefaultListCellRenderer() {
            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                if (c instanceof JLabel) {
                    JLabel l = (JLabel) c;
                    if (value instanceof VirtualFile)
                        l.setText(((VirtualFile) value).getPresentableUrl());
                }
                return c;
            }
        });
        // 设置查找列表渲染器
        findList.setCellRenderer(new DefaultListCellRenderer() {
            private final JPanel panel = new JPanel(new BorderLayout());
            private final JLabel rightLabel = new JLabel();

            {
                rightLabel.setHorizontalTextPosition(RIGHT);
                rightLabel.setOpaque(true);
            }

            @Override
            public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
                Component c = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
                if (value instanceof FindResult) {
                    FindResult v = (FindResult) value;
                    rightLabel.setText(v.getFile().getName() + " " + v.getStartOffsetInParent());
                } else {
                    rightLabel.setText("");
                }

                rightLabel.setBackground(c.getBackground());

                panel.add(c);
                panel.add(rightLabel, BorderLayout.EAST);
                return panel;
            }
        });

        // 打开文件选择器
        choiceButton.addActionListener(e -> FileChooser.chooseFiles(
                new FileChooserDescriptor(true, true, false, false, true, true),
                project,
                // 预选根目录
                project.getProjectFile() == null ? null : ProjectRootManager.getInstance(project).getFileIndex().getContentRootForFile(project.getProjectFile()),
                virtualFiles -> {
                    HashSet<String> vis = new HashSet<>();
                    dirModel.removeAllElements();
                    // 嵌套文件不要
                    virtualFiles.stream()
                            .filter(virtualFile -> {
                                if (virtualFile == null) return false;

                                VirtualFile vf = virtualFile;
                                while (vf != null) {
                                    if (vis.contains(vf.toString())) return false;
                                    vf = vf.getParent();
                                }

                                vis.add(virtualFile.toString());
                                return true;
                            }).forEach(dirModel::addElement);
                }
        ));

        // 查找按钮
        findButton.addActionListener(e -> {
            findModel.removeAllElements();
            findButton.setEnabled(false);
            cancelButton.setText("取消");

            if (worker != null && !worker.isDone())
                worker.cancel(true);

            String tagNameInput = nameField.getText().trim().toLowerCase();
            String keyNameInput = keyField.getText().trim().toLowerCase();
            String keyValueInput = valueField.getText().trim().toLowerCase();
            worker = new FindWorker(tagNameInput, keyNameInput, keyValueInput, project, findButton, cancelButton,
                    findProgress, dirModel, findModel);
            worker.execute();
        });

        // 取消按钮
        cancelButton.addActionListener(e -> {
            if (cancelButton.getText().equals("清空")) {
                // 清空
                findModel.removeAllElements();
            } else {
                // 取消
                if (worker == null) return;

                worker.cancel(true);
                worker = null;
                findButton.setEnabled(true);
                findProgress.setValue(0);
                cancelButton.setText("清空");
            }
        });

        // 双击列表选项
        findList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getClickCount() == 2) {
                    FindResult findResult = findList.getSelectedValue();
                    if (findResult == null) return;

                    PsiFile file = findResult.getFile();
                    int startOffset = findResult.getStartOffsetInParent();
                    file.navigate(true);

                    Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
                    // SelectionModel selectionModel = editor.getSelectionModel();
                    CaretModel caretModel = editor.getCaretModel();
                    ScrollingModel scrollingModel = editor.getScrollingModel();

                    // selectionModel.setSelection(startOffset, startOffset); //选中
                    caretModel.moveToOffset(startOffset); // 移动插入符
                    scrollingModel.scrollToCaret(ScrollType.CENTER); // 滚动，以插入符位置为中间

                }
            }
        });
    }

    public JPanel getContent() {
        return mainPanel;
    }
}
